# 导入蓝图对象
from datetime import datetime

from flask import session

from info.models import User
from . import passport_blue
# 导入flask内置的对象
from flask import  request,jsonify,current_app,make_response
# 导入自定义的状态码
from info.utils.response_code import RET
# 导入图片验证码，人机图灵测试
from info.utils.captcha.captcha import captcha
# 导入redis数据库实例
from info import  redis_store,constants, db
# 导入正则re，随机数random
import re,random
# 导入云通讯
from info.libs.yuntongxun import sms


@passport_blue.route('/image_code')
def generate_image_code():
    '''
    生成图片验证码
    1.获取参数，uuid，图片验证码的后缀名，实现多用户同时请求，在数据库中存储唯一
    2.判断参数是否存在，如果不存在，return终止视图函数
    3.调用captcha扩展生成图片验证码;
    4.在服务器的redis数据库中存储图片验证码的编号和内容
    5.返回图片本身；使用resp=make_response(image)返回
    6.修改响应的数据类型
    '''
    # 获取参数
    image_code_id = request.args.get('image_code_id')
    # 判断参数是否存在
    if not image_code_id:
        return jsonify(errno=RET.PARAMERR,errmsg='参数缺失')
    # 调用captcha工具生成图片验证码
    name,text,image = captcha.generate_captcha()
    # 在redis中保存图片验证码的内容
    try:
        redis_store.setex('ImageCode_'+image_code_id,constants.IMAGE_CODE_REDIS_EXPIRES,text)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='保存图片验证码失败')
    else:
        # 使用响应对象返回图片验证码
        response = make_response(image)
        # 设置响应的数据类型为image/jpg
        response.headers['Content-Type']='image/jpg'
        # 返回响应
        return response


@passport_blue.route('/sms_code',methods=['POST'])
def generate_sms_code():
    '''
    生成短信验证
    1.获取手机号，图形验证码内容和图形验证码编号参数
    2.判断参数的完整性
    3.用正则验证手机号是否符合格式
    4.从redis数据库中获取存储的图片验证码的真实编码数据
    5.判断图片数据是否过期
    6.删除数据库中的图片数据
    7.校验用户的验证码内容和数据库中的真实验证码是否一致
    8.调用随机数，生成验证短信中的随机码，然后以手机号编号存入redis数据库中
    9.调用云通讯接口，发送短信验证码给用户
    10，发送成功和失败都会有个返回值，接收之后返回给前端
    '''
    mobile=request.json.get('mobile')
    image_code=request.json.get('image_code')
    image_code_id=request.json.get('image_code_id')
    if not all([mobile,image_code,image_code_id]):
        return jsonify(errno=RET.PARAMERR,errmsg='参数缺失')
    if not re.match(r'^1[3456789]\d{9}$',mobile):
        return jsonify(errno=RET.DATAERR,errmsg='手机号格式错误')
    try:
        real_image_code = redis_store.get('ImageCode_'+image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='获取图片验证码异常')
    if not real_image_code:
        return jsonify(errno=RET.NODATA,errmsg='图形验证码已过期')
    try:
        redis_store.delete('ImageCode_'+image_code_id)
    except Exception as e:
        current_app.logger.error(e)
    if real_image_code.lower() != image_code.lower():
        print(real_image_code.lower())
        print(image_code.lower())
        return jsonify(errno=RET.DATAERR,errmsg='图形验证码错误')
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='数据查询出错')
    if not user is None:
        return jsonify(errno=RET.DATAEXIST,errmsg='该手机号已注册')
    sms_code = '%06d'% random.randint(0,999999)
    print(sms_code)
    try:
        redis_store.setex('SmsCode_'+mobile,constants.SMS_CODE_REDIS_EXPIRES,sms_code)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='保存随机码失败')
    try:
        ccp=sms.CCP()
        result=ccp.send_template_sms(mobile,[sms_code,constants.SMS_CODE_REDIS_EXPIRES/60],1)
        print(result)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR,errmsg='短信发送异常')
    if result == 0:
        return jsonify(errno=RET.OK,errmsg='发送成功')
    else:
        return jsonify(errno=RET.THIRDERR,errmsg='发送失败')


@passport_blue.route('/register',methods=['POST'])
def register():
    '''
    注册帐号
    1.获取参数手机号，短信验证码，密码
    2.校验参数完整性
    3.检查手机号的格式是否正确
    4.获取存储在redis里面的真实的sms_code，
    5.比较获取的用户输入的sms_code和真实存储的是否一样
    6.删除数据库中存储的短信验证码
    7.判断数据库中是否有手机号，看手机号是否已注册
    8.提交用户信息到数据库中存储
    9.返回数据
    :return:
    '''
    mobile = request.json.get('mobile')
    sms_code = request.json.get('sms_code')
    password = request.json.get('password')
    if not all([mobile,sms_code,password]):
        return jsonify(errno=RET.PARAMERR,errmsg='参数缺失')
    if not re.match(r'^1[3456789]\d{9}$',mobile):
        return jsonify(errno=RET.DATAERR,errmsg='参数错误')
    try:
        real_sms_code = redis_store.get('SmsCode_'+mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='数据查询出错')
    if not real_sms_code:
        return jsonify(errno=RET.NODATA,errmsg='短信验证码已过期')
    if real_sms_code != str(sms_code):
        return jsonify(errno=RET.DATAERR,errmsg='短信验证码异常')
    try:
        redis_store.delete('SmsCode_'+mobile)
    except Exception as e:
        current_app.logger.error(e)
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据查询出错')
    if not user is None:
        return jsonify(errno=RET.DATAEXIST, errmsg='该手机号已注册')
    user= User()
    user.mobile=mobile
    user.nick_name=mobile
    user.password=password
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR,errmsg='用户信息保存失败')
    session['user_id']=user.id
    session['nick_name']=user.nick_name
    session['mobile']=mobile

    return jsonify(errno=RET.OK,errmsg='用户注册成功')


@passport_blue.route('/login',methods=['POST'])
def login():
    '''
    登陆功能
    1.获取参数mobile ，password
    2.校验参数的完整性
    3.检查手机号的格式正确否
    4.从数据库中查询用户手机号是否已经注册
    5.校验密码是否正确
    6.同时判断手机号和密码，只要有一个不正确就返回错误信息
    7.添加用户登陆时间到数据库
    8.缓存用户数据到redis里面
    9.返回相应数据
    :return:
    '''
    mobile = request.json.get('mobile')
    password = request.json.get('password')
    if not all([mobile,password]):
        return jsonify(errno=RET.PARAMERR,errmsg='参数缺失')
    if not re.match(r'^1[3456789]\d{9}$',mobile):
        return jsonify(errno=RET.DATAERR,errmsg='手机号格式错误')
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='数据查询失败')
    if user is None or not user.check_password(password):
        return jsonify(errno=RET.DATAERR,errmsg='手机号或密码错误')
    user.last_login=datetime.now()
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR,errmsg='数据库保存异常')
    session['user_id']=user.id
    session['nick_name']=user.nick_name
    session['mobile']=mobile

    return jsonify(errno=RET.OK,errmsg='登陆成功')


@passport_blue.route('/logout',methods=['DELETE'])
def logout():
    '''
    退出功能实现
    删除redis数据库中存储的用户信息
    :return:
    '''
    session.pop('user_id',None)
    session.pop('mobile',None)
    session.pop('nick_name',None)
    session.pop('avatar_url',None)
    session.pop('is_admin', None)
    return jsonify(errno=RET.OK,errmsg='退出成功')